﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace SpaceshipDuel
{
    /// <summary>
    /// Schiffsstatus
    /// </summary>
    public enum ShipState
    {
        Alive       = 1,
        Exploding   = 2,
        GameOver    = 3,
        Warping     = 4
    }

    /// <summary>
    /// Spezialwaffen
    /// </summary>
    enum SpecialWeapon
    {
        None                = 0,
        ScatterBomb         = 1,    // Schüsse in alle Richtungen
        WarpJump            = 2,    // Teleport an zufälliges Ziel
        AtomRocket          = 3,    // Rakete mit gewaltiger Sprengwirkung und -radius
        ShieldRegeneration  = 4,    // Regeniert das Schild auf volle Stärke
    }

    /// <summary>
    /// Raumschiff des Spielers
    /// </summary>
    public class PlayerShip : GameObject
    {
        #region Private fields

        TextureData shotTextureData;        // Textur für Schüsse
        Texture2D shieldTexture;            // Textur für Schutzschild
        TextureData shieldHudTexture;       // Textur für Schild HUD

        int bulletCount;                    // aktuelle Schussanzahl
        int maxBulletCount;                 // maximale Schussanzahl
        int bulletSpeed;                    // Geschwindigkeit der Schüsse
        int maxBulletDistance;              // Flugweite der Schüsse
        int shieldPower;                    // Schildstärke (="Gesundheit")
        int maxShieldPower;                 // maximale Schildstärke
        int lifeCounter;                    // Anzahl Leben
        float rotation;                     // Wert der Rotationsänderung bei Eingabe
        float speed;                        // Wert der Geschwindigkeitsänderung bei Eingabe
        float rotate_speed;                 // Rotationsgeschwindigkeit
        float nextBulletInterval;           // Intervall zwischen den Schüssen
        float rotationAngle;                // Rotationswinkel des Raumschiffs
        bool isHit;                         // Status Treffer/Kollision
        bool shieldRegenerationIsActive;    // Flag für Schildregeneration
        Vector2 velocity;                   // Geschwindigkeitsvektor
        ShipState shipState;                // Zustand des Raumschiffes
        WeaponLevel weaponLevel;            // Waffentyp = aktuelle Waffenausbaustufe
        SpeedLevel speedLevel;              // Geschwindigkeitslevel
        SpecialWeapon specialWeapon;        // Spezialwaffe
        WaitTimer shieldRegenerationTimer;  // Timer für Schildregeneration
        WaitTimer nextBulletTimer;          // Timer für Schussintervall
        WaitTimer showShieldTimer;          // Timer für Anzeige des Schutzschildes bei Treffer / Kollision
        List<Bullet> bullets;               // Refernz auf Geschossliste
        List<AtomRocket> atomRockets;       // Referenz auf Atomraketenliste
        byte playerNumber;                  // Nummer des Spielers (1 oder 2)
        Random rnd;                         // Zufallsgenerator

        #endregion Private fields

        #region Public properties

        public float RotationAngle
        {
            get { return this.rotationAngle; }
            set { this.rotationAngle = value; }
        }

        public int ShieldPower
        {
            get { return this.shieldPower; }
            set { this.shieldPower = value; }
        }

        public Vector2 Velocity
        {
            get { return this.velocity; }
            set { this.velocity = value; }
        }

        public ShipState CurrentShipState
        {
            get { return this.shipState; }
            set { this.shipState = value; }
        }

        public bool IsHit
        {
            get { return this.isHit; }
            set { this.isHit = value; }
        }

        public int MaxBulletDistance
        {
            get { return this.maxBulletDistance; }
            set { this.maxBulletDistance = value; }
        }

        public int MaxShieldPower
        {
            get { return this.maxShieldPower; }
            set { this.maxShieldPower = value; }
        }

        public int LifeCounter
        {
            get { return this.lifeCounter; }
            set { this.lifeCounter = value; }
        }

        public string WeaponLevelDisplay
        {
            get 
            { 
                switch (this.weaponLevel)
                {
                    default:
                    case WeaponLevel.WL0: return "1";
                    case WeaponLevel.WL1: return "2";
                    case WeaponLevel.WL2: return "3";
                    case WeaponLevel.WL3: return "4";
                    case WeaponLevel.WL4: return "5";
                    case WeaponLevel.WL5: return "6";
                    case WeaponLevel.WL6: return "7";
                    case WeaponLevel.WL7: return "8";
                    case WeaponLevel.WL8: return "9";
                    case WeaponLevel.WL9: return "10";
                }
            }
        }

        public string SpeedLevelDisplay
        {
            get
            {
                switch (this.speedLevel)
                {
                    default:
                    case SpeedLevel.SL0: return "1";
                    case SpeedLevel.SL1: return "2";
                    case SpeedLevel.SL2: return "3";
                    case SpeedLevel.SL3: return "4";
                    case SpeedLevel.SL4: return "5";
                    case SpeedLevel.SL5: return "6";
                    case SpeedLevel.SL6: return "7";
                    case SpeedLevel.SL7: return "8";
                    case SpeedLevel.SL8: return "9";
                    case SpeedLevel.SL9: return "10";
                }
            }
        }

        public string SpecialWeaponDisplay
        {
            get
            {
                switch (specialWeapon)
                {
                    case SpecialWeapon.ScatterBomb:         
                        return Dictionary.GetTranslation("Streubombe", ConfigDataHelper.Language);
                    case SpecialWeapon.WarpJump:            
                        return Dictionary.GetTranslation("Warpsprung", ConfigDataHelper.Language);
                    case SpecialWeapon.AtomRocket:          
                        return Dictionary.GetTranslation("Atomrakete", ConfigDataHelper.Language);
                    case SpecialWeapon.ShieldRegeneration:  
                        return Dictionary.GetTranslation("Schild-Regeneration", ConfigDataHelper.Language);
                    default:                                
                        return " - ";
                }
            }
        }

        public byte PlayerNumber
        {
            get { return this.playerNumber; }
        }

        #endregion Public properties

        #region Construction

        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="newShipTextureData">Textur des Raumschiffs</param>
        /// <param name="newShieldTextureData">Textur des Schutzschildes</param>
        /// <param name="newShotTextureData">Textur der Schüsse</param>
        /// <param name="newCenter">Positionsvektor</param>
        /// <param name="newWorldSize">Größe des Spielfeldes</param>
        /// <param name="newBullets">Liste der Schüsse</param>
        /// <param name="playerNumber">Nummer des Spielers</param>
        /// <param name="newAtomRockets">Liste der Atomraketen</param>
        /// <param name="newLifeCounter">Anzahl der Leben/Raumschiffe des Spielers</param>
        public PlayerShip(TextureData newShipTextureData, TextureData newShieldTextureData, TextureData newShotTextureData, Vector2 newCenter, 
                            int newWorldSize, ref List<Bullet> newBullets, byte playerNumber, ref List<AtomRocket> newAtomRockets, int newLifeCounter = 5)
        {
            textureData = newShipTextureData;
            shieldTexture = newShieldTextureData.texture;
            shotTextureData = newShotTextureData;
            shieldHudTexture = TextureProvider.TexShieldHud;
            center = newCenter;
            rotation = 0f;
            rotationAngle = 0f;
            worldSize = newWorldSize;
            velocity = new Vector2(0, 0);  // Richtungsvektor der aktuellen Ausrichtung setzen (für Schüsse)
            bullets = newBullets;
            bulletCount = 0;
            lifeCounter = newLifeCounter;

            weaponLevel = WeaponLevel.WL0;
            UpdateWeaponLevelStats();

            speedLevel = SpeedLevel.SL0;
            UpdateSpeedLevelStats();
            
            maxShieldPower = 300;
            shieldPower = 100;

            isHit = false;
            showShieldTimer = new WaitTimer(0.1f);
            shipState = ShipState.Alive;

            specialWeapon = SpecialWeapon.None;

            atomRockets = newAtomRockets;

            this.playerNumber = playerNumber;

            rnd = new Random();

            shieldRegenerationTimer = new WaitTimer(0.5f);
            shieldRegenerationIsActive = false;
        }

        #endregion Construction

        #region Public methods

        /// <summary>
        /// Update-Methode
        /// </summary>
        /// <param name="kbs">Tastaturzustand</param>
        /// <param name="gpState">Gamepadzustand</param>
        /// <param name="pk">Steuerungstasten</param>
        /// <param name="gameTime">Zeit</param>
        public void Update(KeyboardState kbs, GamePadState gpState, PlayerKeys pk, GameTime gameTime)
        {
            if (shipState == ShipState.Alive)
            {
                center += velocity;
                CheckPosition();

                // Rotationswinkel berechnen
                rotationAngle += rotation;
                rotationAngle = (float)(rotationAngle % (Math.PI * 2));

                // Eingabe hoch/runter = Vorwärts-/Rückwärtsbewegung
                if (kbs.IsKeyDown(pk.upKey) || (gpState.IsConnected && (gpState.DPad.Up == ButtonState.Pressed || gpState.ThumbSticks.Left.Y > 0)))
                {
                    velocity.X = (float)(Math.Sin(rotationAngle) * speed);
                    velocity.Y = (float)(-Math.Cos(rotationAngle) * speed);
                }
                else if (kbs.IsKeyDown(pk.downKey) || (gpState.IsConnected && (gpState.DPad.Down == ButtonState.Pressed || gpState.ThumbSticks.Left.Y < 0)))
                {
                    // Rückwärts gehts nur halb so schnell, Scotty hat nur den Vorwärtsflug optimiert...
                    velocity.X = (float)(-Math.Sin(rotationAngle) * speed / 2);
                    velocity.Y = (float)(Math.Cos(rotationAngle) * speed / 2);
                }
                else
                {
                    // Raumschiff nachdriften lassen, damit wird alles etwas unpräziser ;-)
                    velocity.X = velocity.X / 1.01f;
                    velocity.Y = velocity.Y / 1.01f;
                }

                // Eingabe links/rechts = Rotation
                if (kbs.IsKeyDown(pk.leftKey) || (gpState.IsConnected && (gpState.DPad.Left == ButtonState.Pressed || gpState.ThumbSticks.Left.X < 0)))
                    rotation = -rotate_speed;
                else if (kbs.IsKeyDown(pk.rightKey) || (gpState.IsConnected && (gpState.DPad.Right == ButtonState.Pressed || gpState.ThumbSticks.Left.X > 0)))
                    rotation = rotate_speed;
                else
                    rotation = 0f;

                // Eingabe Feuer = Schießen
                if (kbs.IsKeyDown(pk.fireKey) || (gpState.IsConnected && gpState.Buttons.A == ButtonState.Pressed))
                    Shoot(gameTime);

                // Eingabe Spezial - Special zünden
                if (specialWeapon != SpecialWeapon.None)
                {
                    if (kbs.IsKeyDown(pk.specialKey) || (gpState.IsConnected && gpState.Buttons.B == ButtonState.Pressed))
                    {
                        switch (specialWeapon)
                        {
                            case SpecialWeapon.ScatterBomb: 
                                ScatterBomb(center);
                                break;
                            case SpecialWeapon.WarpJump:
                                WarpJump(true);
                                break;
                            case SpecialWeapon.AtomRocket:
                                AtomRocket();
                                break;
                            case SpecialWeapon.ShieldRegeneration:
                                shieldRegenerationIsActive = true;
                                shieldRegenerationTimer.Reset();
                                break;
                        }
                        specialWeapon = SpecialWeapon.None;
                    }
                }

                if (isHit == true)
                {
                    if (showShieldTimer.IsElapsed(gameTime.ElapsedGameTime.TotalSeconds))
                        isHit = false;
                }

                if (shieldRegenerationIsActive == true)
                    UpdateShieldRegeneration(gameTime);
            }

            UpdateBullets();
        }

        /// <summary>
        /// Draw-Methode
        /// </summary>
        /// <param name="spriteBatch">Spritebatch</param>
        /// <param name="xOffset">Offset X</param>
        /// <param name="yOffset">Offset Y</param>
        new public void Draw(SpriteBatch spriteBatch, float xOffset, float yOffset)
        {
            if (shipState == ShipState.Alive)
            {
                if (isHit == true)
                {
                    spriteBatch.Draw(shieldTexture, new Vector2(center.X + xOffset, center.Y + yOffset), null, Color.White, rotationAngle, new Vector2(textureData.halfwidth, textureData.halfheight), 1.0f, SpriteEffects.None, 0f);
                }

                spriteBatch.Draw(textureData.texture, new Vector2(center.X + xOffset, center.Y + yOffset), new Rectangle(0, 0, textureData.width, textureData.height), Color.White, rotationAngle, new Vector2(textureData.halfwidth, textureData.halfheight), 1.0f, SpriteEffects.None, 0f);

                DrawShieldHud(spriteBatch, xOffset, yOffset);
            }

            for (int i = 0; i < bullets.Count; i++)
                bullets[i].Draw(spriteBatch, xOffset, yOffset);
        }

        /// <summary>
        /// Schadensverteilung
        /// </summary>
        /// <param name="damage">Schaden, den das Schiff erhält</param>
        public void Hit(int damage = 1)
        {
            if (shipState == ShipState.Alive)   // -> Schiff kann beim Warpen keinen Schaden erhalten
            {
                shieldPower -= damage;

                if (isHit == false)
                {
                    showShieldTimer.Reset();
                    isHit = true;
                }
            }
        }

        /// <summary>
        /// Schiff wurde zerstört und explodiert jetzt erstmal
        /// </summary>
        public void ShipExplodes()
        {
            shipState = ShipState.Exploding;
            SoundProviderOgg.SfxPlayershipExplosion.Play();

            switch (weaponLevel)
            {
                case WeaponLevel.WL9: weaponLevel = WeaponLevel.WL8; break;
                case WeaponLevel.WL1: weaponLevel = WeaponLevel.WL0; break;
                case WeaponLevel.WL2: weaponLevel = WeaponLevel.WL1; break;
                case WeaponLevel.WL3: weaponLevel = WeaponLevel.WL2; break;
                case WeaponLevel.WL4: weaponLevel = WeaponLevel.WL3; break;
                case WeaponLevel.WL5: weaponLevel = WeaponLevel.WL4; break;
                case WeaponLevel.WL6: weaponLevel = WeaponLevel.WL5; break;
                case WeaponLevel.WL7: weaponLevel = WeaponLevel.WL6; break;
                case WeaponLevel.WL8: weaponLevel = WeaponLevel.WL7; break;
            }

            UpdateWeaponLevelStats();

            switch (speedLevel)
            {
                case SpeedLevel.SL1: speedLevel = SpeedLevel.SL0; break;
                case SpeedLevel.SL2: speedLevel = SpeedLevel.SL1; break;
                case SpeedLevel.SL3: speedLevel = SpeedLevel.SL2; break;
                case SpeedLevel.SL4: speedLevel = SpeedLevel.SL3; break;
                case SpeedLevel.SL5: speedLevel = SpeedLevel.SL4; break;
                case SpeedLevel.SL6: speedLevel = SpeedLevel.SL5; break;
                case SpeedLevel.SL7: speedLevel = SpeedLevel.SL6; break;
                case SpeedLevel.SL8: speedLevel = SpeedLevel.SL7; break;
                case SpeedLevel.SL9: speedLevel = SpeedLevel.SL8; break;
            }

            UpdateSpeedLevelStats();
        }

        /// <summary>
        /// Respawn, nachdem das Schiff explodiert ist
        /// </summary>
        /// <param name="newCenter">neue Position</param>
        public void Respawn(Vector2 newCenter)
        {
            if (lifeCounter > 1)
            {
                lifeCounter--;
                center = newCenter;
                rotation = 0f;
                rotationAngle = 0f;
                velocity = new Vector2(0, 0);
                bulletCount = 0;
                shieldPower = 100;
                isHit = false;
                shipState = ShipState.Alive;
            }
            else
            {
                lifeCounter = 0;
                shipState = ShipState.GameOver;
            }
        }

        /// <summary>
        /// Schiff hat ein Upgrade aufgesammelt
        /// </summary>
        /// <param name="type">Typ des Upgrades</param>
        public void Upgrade(UpgadeTypes type)
        {
            switch (type)
            {
                case UpgadeTypes.Weapon:
                    UpgradeWeapon();
                    break;

                case UpgadeTypes.Speed:
                    UpgradeSpeed();
                    break;

                case UpgadeTypes.ShieldRefresh:
                    UpgradeShieldRefresh();
                    break;

                case UpgadeTypes.Special:
                    UpgradeSpecial();
                    break;
            }
        }

        /// <summary>
        /// Schiff macht einen Warpsprung
        /// </summary>
        /// <param name="enable"></param>
        public void WarpJump(bool enable)
        {
            if (enable)
            {
                shipState = ShipState.Warping;
                SoundProviderOgg.SfxPlayershipTeleport.Play();
            }
            else
                shipState = ShipState.Alive;
        }

        #endregion Public methods

        #region Private methods

        /// <summary>
        /// Upgrade für Waffen aktivieren
        /// </summary>
        private void UpdateWeaponLevelStats()
        {
            WeaponLevelStats wls = UpgradeHelper.GetWeaponLevelStats(weaponLevel);

            maxBulletCount = wls.maxBulletCount;
            maxBulletDistance = wls.maxBulletDistance;
            bulletSpeed = wls.bulletSpeed;
            nextBulletInterval = wls.nextBulletInterval;

            nextBulletTimer = new WaitTimer(nextBulletInterval);
        }

        /// <summary>
        /// Upgrade für Antrieb aktivieren
        /// </summary>
        private void UpdateSpeedLevelStats()
        {
            SpeedLevelStats sls = UpgradeHelper.GetSpeedLevelStats(speedLevel);
            rotate_speed = sls.rotate_speed;
            speed = sls.speed;
        }

        /// <summary>
        /// Upgrade der Bordwaffe
        /// </summary>
        private void UpgradeWeapon()
        {
            switch (weaponLevel)
            {
                case WeaponLevel.WL0: weaponLevel = WeaponLevel.WL1; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL1: weaponLevel = WeaponLevel.WL2; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL2: weaponLevel = WeaponLevel.WL3; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL3: weaponLevel = WeaponLevel.WL4; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL4: weaponLevel = WeaponLevel.WL5; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL5: weaponLevel = WeaponLevel.WL6; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL6: weaponLevel = WeaponLevel.WL7; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL7: weaponLevel = WeaponLevel.WL8; UpdateWeaponLevelStats(); break;
                case WeaponLevel.WL8: weaponLevel = WeaponLevel.WL9; UpdateWeaponLevelStats(); break;
            }
        }

        /// <summary>
        /// Upgrade von Geschwindigkeit
        /// </summary>
        private void UpgradeSpeed()
        {
            switch (speedLevel)
            {
                case SpeedLevel.SL0: speedLevel = SpeedLevel.SL1; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL1: speedLevel = SpeedLevel.SL2; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL2: speedLevel = SpeedLevel.SL3; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL3: speedLevel = SpeedLevel.SL4; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL4: speedLevel = SpeedLevel.SL5; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL5: speedLevel = SpeedLevel.SL6; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL6: speedLevel = SpeedLevel.SL7; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL7: speedLevel = SpeedLevel.SL8; UpdateSpeedLevelStats(); break;
                case SpeedLevel.SL8: speedLevel = SpeedLevel.SL9; UpdateSpeedLevelStats(); break;
            }
        }

        /// <summary>
        /// Upgrade Aufladen des Schildes
        /// </summary>
        private void UpgradeShieldRefresh()
        {
            shieldPower += 50;

            if (shieldPower > maxShieldPower)
                shieldPower = maxShieldPower;
        }

        /// <summary>
        /// Upgrade Spezialwaffe
        /// </summary>
        private void UpgradeSpecial()
        {
            // Special wird per Zufall gesetzt
            specialWeapon = (SpecialWeapon)(rnd.Next(4)+1);
        }

        /// <summary>
        /// Raumschiff feuert einen Schuss ab
        /// </summary>
        /// <param name="gameTime"></param>
        private void Shoot(GameTime gameTime)
        {
            if (nextBulletTimer.IsElapsed(gameTime.ElapsedGameTime.TotalSeconds) == true)
            {
                switch (weaponLevel)
                {
                    case WeaponLevel.WL2:
                    case WeaponLevel.WL3:
                        ShootDoubleShot(gameTime);
                        break;
                    case WeaponLevel.WL4:
                    case WeaponLevel.WL5:
                        ShootTripleShot(gameTime);
                        break;
                    case WeaponLevel.WL6:
                    case WeaponLevel.WL7:
                        ShootFiveShot(gameTime);
                        break;
                    case WeaponLevel.WL8:
                    case WeaponLevel.WL9:
                        ShootSixShot(gameTime);
                        break;
                    default:
                        ShootSingleShot(gameTime);
                        break;
                }
            }
        }

        /// <summary>
        /// Shooting single shots
        /// </summary>
        /// <param name="gameTime"></param>
        private void ShootSingleShot(GameTime gameTime)
        {
            if (bulletCount < maxBulletCount)
            {
                bulletCount++;

                Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
                bulletDirection.Normalize();
                Vector2 bulletPosition = center + bulletDirection * 32;
                Bullet bullet = new Bullet(shotTextureData, bulletPosition, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);

                bullets.Add(bullet);
                nextBulletTimer.Reset();

                if (playerNumber == 1)
                    SoundProviderOgg.SfxLaserPlayer1.Play();
                else
                    SoundProviderOgg.SfxLaserPlayer2.Play();
            }
        }

        /// <summary>
        /// Shooting double shots
        /// </summary>
        /// <param name="gameTime"></param>
        private void ShootDoubleShot(GameTime gameTime)
        {
            if (bulletCount < (maxBulletCount - 1))
            {
                bulletCount = bulletCount + 2;

                Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
                bulletDirection.Normalize();
                Vector2 tangente = new Vector2(-bulletDirection.Y, bulletDirection.X);
                Vector2 bulletPosition = center + bulletDirection * 32;
                Bullet bullet1 = new Bullet(shotTextureData, bulletPosition + tangente * 5, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet2 = new Bullet(shotTextureData, bulletPosition - tangente * 5, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);

                bullets.Add(bullet1);
                bullets.Add(bullet2);
                nextBulletTimer.Reset();

                if (playerNumber == 1)
                    SoundProviderOgg.SfxLaserPlayer1.Play();
                else
                    SoundProviderOgg.SfxLaserPlayer2.Play();
            }
        }

        /// <summary>
        /// Shooting triple shots
        /// </summary>
        /// <param name="gameTime"></param>
        private void ShootTripleShot(GameTime gameTime)
        {
            if (bulletCount < (maxBulletCount - 2))
            {
                bulletCount = bulletCount + 3;

                //float angle = (float)Math.PI / 12;
                float angle = (float)Math.PI / 40;

                Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
                bulletDirection.Normalize();
                Vector2 tangente = new Vector2(-bulletDirection.Y, bulletDirection.X);
                
                Vector2 bulletPosition = center + bulletDirection * 32;
                Bullet bullet1 = new Bullet(shotTextureData, bulletPosition + tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle + angle, bulletDirection + (tangente / /*3*/ 10), maxBulletDistance);
                Bullet bullet2 = new Bullet(shotTextureData, bulletPosition,                 this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet3 = new Bullet(shotTextureData, bulletPosition - tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle - angle, bulletDirection - (tangente / /*3*/ 10), maxBulletDistance);

                bullets.Add(bullet1);
                bullets.Add(bullet2);
                bullets.Add(bullet3);
                nextBulletTimer.Reset();

                if (playerNumber == 1)
                    SoundProviderOgg.SfxLaserPlayer1.Play();
                else
                    SoundProviderOgg.SfxLaserPlayer2.Play();
            }
        }

        /// <summary>
        /// Shooting five shots
        /// </summary>
        /// <param name="gameTime"></param>
        private void ShootFiveShot(GameTime gameTime)
        {
            if (bulletCount < (maxBulletCount - 4))
            {
                bulletCount = bulletCount + 5;

                float angle = (float)Math.PI / 8;

                Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
                bulletDirection.Normalize();
                Vector2 tangente = new Vector2(-bulletDirection.Y, bulletDirection.X);
                Vector2 bulletPosition = center + bulletDirection * 32;
                Bullet bullet1 = new Bullet(shotTextureData, bulletPosition + tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle + angle, bulletDirection + (tangente / 2), maxBulletDistance);
                Bullet bullet2 = new Bullet(shotTextureData, bulletPosition,                 this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet3 = new Bullet(shotTextureData, bulletPosition - tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle - angle, bulletDirection - (tangente / 2), maxBulletDistance);

                bulletDirection = -bulletDirection;
                bulletPosition = center + bulletDirection * 32;
                Bullet bullet4 = new Bullet(shotTextureData, bulletPosition + tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet5 = new Bullet(shotTextureData, bulletPosition - tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);

                bullets.Add(bullet1);
                bullets.Add(bullet2);
                bullets.Add(bullet3);
                bullets.Add(bullet4);
                bullets.Add(bullet5);
                nextBulletTimer.Reset();

                if (playerNumber == 1)
                    SoundProviderOgg.SfxLaserPlayer1.Play();
                else
                    SoundProviderOgg.SfxLaserPlayer2.Play();
            }
        }

        /// <summary>
        /// Shooting six shots
        /// </summary>
        /// <param name="gameTime"></param>
        private void ShootSixShot(GameTime gameTime)
        {
            if (bulletCount < (maxBulletCount - 5))
            {
                bulletCount = bulletCount + 6;

                float angle = (float)Math.PI / 8;

                Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
                bulletDirection.Normalize();
                Vector2 tangente = new Vector2(-bulletDirection.Y, bulletDirection.X);
                Vector2 bulletPosition = center + bulletDirection * 32;
                Bullet bullet1 = new Bullet(shotTextureData, bulletPosition + tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle + angle, bulletDirection + (tangente / 2), maxBulletDistance);
                Bullet bullet2 = new Bullet(shotTextureData, bulletPosition + tangente * 5, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet3 = new Bullet(shotTextureData, bulletPosition - tangente * 5, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet4 = new Bullet(shotTextureData, bulletPosition - tangente * 10, this.worldSize, this.speed + bulletSpeed, this.rotationAngle - angle, bulletDirection - (tangente / 2), maxBulletDistance);

                bulletDirection = -bulletDirection;
                bulletPosition = center + bulletDirection * 32;
                Bullet bullet5 = new Bullet(shotTextureData, bulletPosition + tangente * 10, this.worldSize, this.speed + bulletSpeed, (float)(this.rotationAngle-Math.PI-angle), bulletDirection + (tangente / 2), maxBulletDistance);
                Bullet bullet6 = new Bullet(shotTextureData, bulletPosition - tangente * 10, this.worldSize, this.speed + bulletSpeed, (float)(this.rotationAngle-Math.PI+angle), bulletDirection - (tangente / 2), maxBulletDistance);

                bullets.Add(bullet1);
                bullets.Add(bullet2);
                bullets.Add(bullet3);
                bullets.Add(bullet4);
                bullets.Add(bullet5);
                bullets.Add(bullet6);
                nextBulletTimer.Reset();

                if (playerNumber == 1)
                    SoundProviderOgg.SfxLaserPlayer1.Play();
                else
                    SoundProviderOgg.SfxLaserPlayer2.Play();
            }
        }

        // Eine Streubombe abfeuern
        private void ScatterBomb(Vector2 center)
        {
            for (int i = 0; i < 360; i = i + 5)
            {
                Vector2 bulletDirection = new Vector2((float)Math.Sin(i * Math.PI / 180), (float)-Math.Cos(i * Math.PI / 180));
                bulletDirection.Normalize();
                Vector2 bulletPosition = center + bulletDirection * 32;
                Vector2 tangente = new Vector2(-bulletDirection.Y, bulletDirection.X);
                Bullet newBullet1 = new Bullet(shotTextureData, bulletPosition + tangente, this.worldSize, 10.0f, (float)(i * Math.PI / 180), bulletDirection, 600.0f, 10);
                Bullet newBullet2 = new Bullet(shotTextureData, bulletPosition + tangente, this.worldSize, 8.0f, (float)(i * Math.PI / 180), bulletDirection, 800.0f, 10);
                Bullet newBullet3 = new Bullet(shotTextureData, bulletPosition + tangente, this.worldSize, 6.0f, (float)(i * Math.PI / 180), bulletDirection, 1000.0f, 10);
                bullets.Add(newBullet1);
                bullets.Add(newBullet2);
                bullets.Add(newBullet3);
            }

            if (playerNumber == 1)
                SoundProviderOgg.SfxLaserPlayer1.Play();
            else
                SoundProviderOgg.SfxLaserPlayer2.Play();
        }

        // Eine Atomrakete abfeuern
        private void AtomRocket()
        {
            Vector2 rocketDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
            rocketDirection.Normalize();
            Vector2 rocketPosition = center + rocketDirection * (32 + 25);
            atomRockets.Add(new AtomRocket(center, worldSize, speed + 1, rotationAngle));

            // Lauch-Sound ?
        }

        // Regeneriere Schutzschild bis Maximum
        private void UpdateShieldRegeneration(GameTime gameTime)
        {
            if (shieldRegenerationTimer.IsElapsed(gameTime.ElapsedGameTime.TotalSeconds) == true)
            {
                shieldPower = Math.Min(maxShieldPower, shieldPower + 5);
            }

            if (shieldPower >= maxShieldPower)
                shieldRegenerationIsActive = false;
        }
        
        /// <summary>
        /// Aktualisierung der Geschosse
        /// </summary>
        private void UpdateBullets()
        {
            for (int i = 0; i < bullets.Count; i++)
            {
                bullets[i].Update();

                if (bullets[i].DestroyMe == true)
                {
                    bullets.RemoveAt(i);
                    i--;
                    bulletCount--;
                }
            }
        }

        /// <summary>
        /// Korrektur der Raumschiffposition beim Flug über Spielfeldgrenzen hinweg
        /// </summary>
        private void CheckPosition()
        {
            if (center.X < 0)
                center.X = worldSize + center.X;
            else if (center.X >= worldSize)
                center.X = center.X - worldSize;

            if (center.Y < 0)
                center.Y = worldSize + center.Y;
            else if (center.Y >= worldSize)
                center.Y = center.Y - worldSize;
        }

        /// <summary>
        /// zeichne HUD für Schildstärke (die kreisförmige Schildanzeige um das Schiff)
        /// </summary>
        private void DrawShieldHud(SpriteBatch spriteBatch, float xOffset, float yOffset)
        {
            int frame = Math.Max(Math.Min((shieldPower - 1) / 10, 29), 0);
            int frameX = frame % 10;
            int frameY = frame / 10;
            Color shieldHudColor = new Color(160, 160, 255);
            Vector2 position = new Vector2(center.X + xOffset, center.Y + yOffset);
            Rectangle sourceRect = new Rectangle(frameX * shieldHudTexture.tileWidth, frameY * shieldHudTexture.tileHeight, shieldHudTexture.tileWidth, shieldHudTexture.tileHeight);
            Vector2 origin = new Vector2(shieldHudTexture.tileWidth / 2, shieldHudTexture.tileHeight / 2);
            spriteBatch.Draw(shieldHudTexture.texture, position, sourceRect, shieldHudColor, rotationAngle, origin, 1.0f, SpriteEffects.None, 0);
        }

        #endregion Private methods
    }
}
